package com.tanx.cqrs.spring.boot.autoconfig;

import com.tanx.cqrs.command.handler.CommandHandlerResolver;
import com.tanx.cqrs.event.handler.EventHandlerResolver;
import com.tanx.cqrs.eventsourcing.EventSourcingRepository;
import com.tanx.cqrs.eventsourcing.handler.EventSourcingHandlerResolver;
import com.tanx.cqrs.infrastructure.spring.command.handler.SpringBeanCommandHandlerResolverImpl;
import com.tanx.cqrs.infrastructure.spring.event.handler.SpringBeanEventHandlerResolverImpl;
import com.tanx.cqrs.infrastructure.spring.event.store.EventStoreRepositoryFactory;
import com.tanx.cqrs.infrastructure.spring.eventsourcing.EventSourcingRepositoryImpl;
import com.tanx.cqrs.infrastructure.spring.eventsourcing.handler.SpringBeanEventSourcingHandlerResolverImpl;
import com.tanx.cqrs.infrastructure.spring.saga.SpringBeanSagaHandlerResolverImpl;
import com.tanx.cqrs.saga.SagaHandlerResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置cqrs主要组件
 */
@Configuration
public class SpringAnnotationDrivenConfiguration {

    @Autowired
    private ApplicationContext context;

    @ConditionalOnClass(SpringBeanCommandHandlerResolverImpl.class)
    @ConditionalOnMissingBean
    @Bean
    public CommandHandlerResolver commandHandlerResolver(EventSourcingRepository repository) {
        SpringBeanCommandHandlerResolverImpl springBeanCommandHandlerResolver = new SpringBeanCommandHandlerResolverImpl(repository, context);
        springBeanCommandHandlerResolver.registerAllHandler();
        return springBeanCommandHandlerResolver;
    }

    @ConditionalOnClass(SpringBeanEventHandlerResolverImpl.class)
    @ConditionalOnMissingBean
    @Bean
    public EventHandlerResolver eventHandlerResolver() {
        SpringBeanEventHandlerResolverImpl handlerResolver = new SpringBeanEventHandlerResolverImpl(context);
        handlerResolver.registerAllHandler();
        return handlerResolver;
    }


    @ConditionalOnClass(SpringBeanEventSourcingHandlerResolverImpl.class)
    @ConditionalOnMissingBean
    @Bean
    public EventSourcingHandlerResolver eventSourcingHandlerResolver() {
        SpringBeanEventSourcingHandlerResolverImpl handlerResolver = new SpringBeanEventSourcingHandlerResolverImpl(context);
        handlerResolver.registerAllHandler();
        return handlerResolver;
    }

    @ConditionalOnClass(SpringBeanSagaHandlerResolverImpl.class)
    @ConditionalOnMissingBean
    @Bean
    public SagaHandlerResolver sagaHandlerResolver() {
        SpringBeanSagaHandlerResolverImpl handlerResolver = new SpringBeanSagaHandlerResolverImpl(context);
        handlerResolver.registerAllHandler();
        return handlerResolver;
    }

    @ConditionalOnClass(EventSourcingRepositoryImpl.class)
    @ConditionalOnMissingBean
    @Bean
    public EventSourcingRepository eventSourcingRepository(EventSourcingHandlerResolver resolver,
                                                           EventStoreRepositoryFactory factory,
                                                           ApplicationContext context,
                                                           AutowireCapableBeanFactory beanFactory) {
        return new EventSourcingRepositoryImpl(resolver, context, factory, beanFactory);
    }

    @ConditionalOnClass(EventStoreRepositoryFactory.class)
    @ConditionalOnMissingBean
    @Bean
    public EventStoreRepositoryFactory repositoryFactory() {
        return new EventStoreRepositoryFactory(context);
    }


}
